package com.uiao.commons;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashSet;
import java.util.Set;

import javax.validation.constraints.Null;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.realm.AuthenticatingRealm;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;

/**
 * Shiro 权限认证
 * 
 * 这个类对应spring-config.xml里声明的bean jdbcRealm，spring会加载它的实例
 * 
 * @author Administrator
 *
 */
public class ShiroRealm extends AuthorizingRealm {

	/**
	 * Shiro登录认证
	 * 
	 * 在LogonController里实例currentUser中的login(token)方法中的token会作为参数传到这
	 * 
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(
			AuthenticationToken token) throws AuthenticationException {
		
		System.out.println("开始登录认证");
		SimpleAuthenticationInfo info = null;
		
		// 1.将token转换成UsernamePasswordToken
		UsernamePasswordToken upToken = (UsernamePasswordToken) token;
		// 2.获取用户名
		String username = upToken.getUsername();
		// 2.查询数据库
		try {
			Class.forName("com.mysql.jdbc.Driver");

			String url = "jdbc:mysql://localhost:3306/shiro?characterEncoding=utf-8";

			Connection conn = DriverManager.getConnection(url, "root", "123");

			String sql = "select * from user where name = ?";
			PreparedStatement ps = conn.prepareStatement(sql);
			ps.setString(1, username);
			System.out.println(sql + username);
			ResultSet resultSet = ps.executeQuery();

			if (resultSet.next()) {
				Object principal = username;

				Object credentials = resultSet.getString("password");

				String realmName = this.getName();

				// token中的密码进行盐值加密
				ByteSource salt = new ByteSource.Util().bytes(resultSet
						.getString("id"));
				// 封装数据库中获取的密码，进行MD5及盐值加密
				SimpleHash sh = new SimpleHash("MD5", credentials, salt, 5);

				// 获取正确数据，具体的认证由shiro api来完成
				info = new SimpleAuthenticationInfo(principal, sh, salt,
						realmName);

			} else {
				throw new AuthenticationException();
			}

		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}

		return info;
	}

	/**
	 * Shiro 授权
	 * 
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(
			PrincipalCollection principals) {
		
		System.out.println("开始授权");
		SimpleAuthorizationInfo info = null;

		try {
			Class.forName("com.mysql.jdbc.Driver");

			String url = "jdbc:mysql://localhost:3306/shiro?characterEncoding=utf-8";

			Connection conn = DriverManager.getConnection(url, "root", "123");

			String sql = "select * from user where name = ?";
			
			PreparedStatement ps = conn.prepareStatement(sql);
			String username = principals.toString();

			ps.setString(1, username);
			System.out.println(sql + username);
			ResultSet resultSet = ps.executeQuery();

			if (resultSet.next()) {
				Set<String> roles = new HashSet<String>();
				roles.add(resultSet.getString("role"));
				info = new SimpleAuthorizationInfo(roles);

			} else {
				throw new AuthenticationException();
			}

		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return info;
	}

}
